home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 5 / SAFARI_I / SAFARI_I.C
Text File  |  1991-09-08  |  52KB  |  2,077 lines

  1. /*    Code release for Safari II 1.1.
  2.     Changes since 1.0 release:
  3.         It's now FREE!  (please send comments & a postcard)
  4.         The sicn's were eliminated from the apple menu so
  5.           it should now work on older systems
  6.         The dialog box in which I begged for a job is gone
  7.            (I've found work, thanks!)
  8.         The option to 'score when hit' in rectangle
  9.            surrounding animal now works.
  10.            
  11.     There still seems to be problems with the sound playing
  12.     on older 68000 Macs.  Any advice on this problem, or
  13.     more descript diagnoses would be appreciated.
  14.  
  15.     SAFARI II ⌐ 1991 by John Gallaugher
  16.         A program written in Think C.  Portions copywright
  17.         Symantec and Apple Computer.
  18.  
  19.     In 1985 I wrote a program called Safari to try to teach myself
  20.     the Macintosh toolbox.  The original Safari was simple and cute, 
  21.     but it was also a program which doesn't work on today's machines.
  22.     Safari II is an update to the orginal Safari.  It should work
  23.     on all Macs with at least 1 meg of memory running system 6.0.x
  24.     or greater.
  25.     
  26.     Although I have done quite a bit of Macintosh database development,
  27.     I have never programmed professioanlly in the toolbox or in C.
  28.     As such, please excuse the clumsiness of some of this code.  I
  29.     am distributing the source code and game for free in hopes
  30.     that it will help others learn some of the basics of Macintosh
  31.     game development.  My experience has found that there's not
  32.     much free source code out there to help the would-be game
  33.     developmer.  I hope my modest submition helps some folks get
  34.     started.
  35.     
  36.     Although this product is offerd for free, I DO ask those pros
  37.     and semi-pros out there to offer suggestions on how I can
  38.     improve this code.  Since I'm pretty green in toolbox coding
  39.     I would greatly appreciate advice.  Please don't hold back, 
  40.     criticize me to the hilt!  I need and welcome the help.
  41.     
  42.     Also, please don't distribute any modified versions of
  43.     Safari.  I welcome you to learn from the code and encourage
  44.     you to produce original work, but I would like all updates
  45.     of the game to pass through me.
  46.     
  47.     Lastly, please send comments!  I love to hear from folks who
  48.     have received my game.  My E-Mail addresses are:
  49.     CIS - 70137,763
  50.     AOL - GALLAUGHER
  51.     
  52.     If you'd care to send any U.S. Mail (I love postcards), forward
  53.     them to:
  54.         Safari
  55.         c/o John Gallaugher
  56.         Three Allegheny Center #118
  57.         Pittsburgh, PA 15212
  58.         
  59.     A special thanks to the helpful folks at the Boston Computer
  60.     Society's MacTech group, and to the outstanding faculty of
  61.     the Boston College Computer Science Program for their patient
  62.     help in answering my silly questions.
  63.     
  64.     This program seems to work fine on my 4 meg LC running under System 7.0
  65.     if you run into any problems, PLEASE let me know.
  66.     
  67.     RESOURCE NOTE:  All sounds were created using the microphone on a Macintosh LC.
  68.         All pictures were created using MacPaint.  The 'RGN ' resources which
  69.         are used to detect the boundries of the animal bodies were created using
  70.         a utilty program called 'Regions' created by the late Duane Blehm (it should
  71.         be available via local user groups and on-line services).  All other
  72.         resources were created directly in ResEdit.
  73.  */
  74.  
  75. #include <Sound.h> /* adds routines need to play Asynch Sound */
  76.  
  77. /* sorry about any inconsistencies in declaring resource numbers.  I started
  78.     and stopped the project several times and added things on the fly without
  79.     thinking of a logical numbering system.  Feel free to suggest a convention */
  80.  
  81. #define    NIL_POINTER            0L
  82. #define M_T_F        ((void *)-1L) /* for "Move To Front".  Used in setting up windows */
  83. #define    BASE_RES_ID            400
  84. #define MOVE_TO_FRONT        -1L
  85. #define    REMOVE_ALL_EVENTS    0
  86.  
  87. #define    BORDER                6  /* number of pixels between window and screen width */
  88. #define    TITLE_BAR_HEIGHT    19 /* I guessed, is there a TB call to get this? */
  89. #define    TICK_DELAY            1  /* this cycles the animation through 1 tick, or 1/60th of a second */
  90.  
  91. /* Menu IDs */
  92. #define    APPLE_MENU_ID    1
  93. #define    FILE_MENU_ID    401
  94. #define    EDIT_MENU_ID    402
  95. #define    GAME_MENU_ID    403
  96.  
  97. /* Menu Items */
  98. #define    ABOUT_ITEM    1
  99. #define    NEW_GAME_ITEM    1
  100. #define    PAUSE_RESUME_ITEM    2
  101. #define    STOP_ITEM    3
  102. #define    QUIT_ITEM    5
  103. #define    UNDO_ITEM    1
  104. #define    CUT_ITEM    3
  105. #define    COPY_ITEM    4
  106. #define    PASTE_ITEM    5
  107. #define    CLEAR_ITEM    6
  108. #define    GAME_OPTIONS_ITEM    1
  109. #define    ANIMAL_POINT_VALUES_ITEM    2
  110. #define    HALL_OF_FAME_ITEM    3
  111.  
  112. /* Alerts */
  113. #define    ERROR_ALERT_ID    401
  114. #define    ERROR_EDIT_TEXT    402
  115. #define    EXPIRED_ALERT    403
  116.  
  117. /* Dialogs */
  118. #define    GAME_OPTIONS_DIALOG            200
  119. #define    SAVE_HIGH_SCORES_DIALOG        300
  120. #define    ANIMAL_POINT_VALUES_DIALOG    129
  121. #define    INTRO_DIALOG                475
  122. #define    ABOUT_DIALOG                476
  123. #define    PLAYER_NAME_DIALOG            500
  124. #define    HALL_OF_FAME_DIALOG            550
  125.  
  126. /* Dialog Items */
  127. #define OK_BUTTON    1
  128. #define    SAVE_AND_CLEAR_BUTTON    2
  129. #define    CANCEL_BUTTON    3
  130. #define    MINUTES                5
  131. #define    SECONDS                6
  132. #define    MAX_ESCAPED            7
  133. #define    ESCAPED_RADIO    10
  134. #define    TIMED_RADIO        11
  135. #define    NINE_INCH_RADIO            22
  136. #define    CURRENT_SCREEN_RADIO    23
  137. #define    INCREASE_YES_RADIO    19
  138. #define    INCREASE_NO_RADIO    20
  139. #define    SLOW_RADIO        14
  140. #define    MEDIUM_RADIO    15
  141. #define    FAST_RADIO        16
  142. #define    IN_ANIMAL_OUTLINE_RADIO    28
  143. #define    IN_BOX_SURROUNDING_ANIMAL_RADIO    27
  144. #define    PLAYER_NAME_ITEXT    3
  145. #define    CLEAR_SCORES_BUTTON    2
  146. #define    OK_APV_DBOX            10
  147. #define    SHOW_INTRO_SCREEN    2
  148. #define    HELP_BUTTON    3
  149. #define    HEAD_ICON    5
  150. #define    OUCH_ICON    7
  151.  
  152. /* icons */
  153. #define    MY_HEAD        476
  154. #define    OUCH_HEAD    477
  155.  
  156. /* Error Strings */
  157. #define    NO_MBAR    BASE_RES_ID
  158. #define    NO_MENU    BASE_RES_ID+1
  159. #define    NO_WIND    BASE_RES_ID+3
  160. #define NO_STR    BASE_RES_ID+4
  161. #define CANT_LOAD_SND    BASE_RES_ID+5
  162. #define    MINUTES_ERROR    BASE_RES_ID+6
  163. #define    SECONDS_ERROR    BASE_RES_ID+7
  164. #define    ESCAPED_ERROR    BASE_RES_ID+8
  165. #define    NO_RGN    BASE_RES_ID+9
  166.  
  167. /* 'STR ' Resource ID's */
  168. #define    TIMED_OR_ESCAPED    200
  169. #define ANIMAL_SPEED        201
  170. #define    WINDOW_SIZE            202
  171. #define    INCREASE_SPEED        203
  172. #define    SCORE_WHEN_HIT        204
  173. #define    MINUTES_STRING        205
  174. #define    SECONDS_STRING        206
  175. #define    MAX_ESCAPED_STRING    207
  176. #define    HIGH_SCORE_STRING    128
  177. #define    HIGH_NAMES_STRING    131
  178.  
  179. #define    ON    1
  180. #define    OFF    0
  181. #define    TIMED_GAME        0
  182. #define    ESCAPED_GAME    1
  183.  
  184. /* Cursor */
  185. #define    CROSSHAIR    400
  186.  
  187. /* Button Types */
  188. #define    PLAY_AGAIN_BUTTON    128
  189. #define    QUIT_BUTTON            129
  190.  
  191. /* Sounds */
  192. #define NIL_SOUND_CHANNEL    0L
  193. #define    TARZAN_SOUND        410
  194. #define    INTRO_SOUND            411
  195. #define    OUCH_SOUND            412
  196.  
  197. /* PICTs */
  198. #define ANIMAL_PICTURE    400  /* this is the picture which contains the animals for your bitmaps */
  199.  
  200. /* ANIMALS */
  201. #define    RHINO        1
  202. #define    ELEPHANT    2
  203. #define    ZEBRA        3
  204. #define    GORILLA        4
  205. #define    ANTELOPE    5
  206. #define    GIRAFFE        6
  207. #define    LION        7
  208. #define    CHEETAH        8
  209. #define WARTHOG        9
  210.  
  211. #define    DRAG_THRESHOLD    30
  212.  
  213. #define    WINDOW_HOME_LEFT    5
  214. #define    WINDOW_HOME_TOP    45
  215. #define    NEW_WINDOW_OFFSET    20
  216.  
  217. #define    MIN_SLEEP    0L
  218. #define    NIL_MOUSE_REGION    0l  /* used in WaitNextEvent */
  219.  
  220. #define    BRING_TO_FRONT    TRUE      /* used in MoveWindow */
  221.  
  222. #define    WNE_TRAP_NUM    0x60
  223. #define    UNIMPL_TRAP_NUM    0x9F
  224.  
  225. #define    NIL_STRING    "\p"
  226. #define    HOPELESSLY_FATAL_ERROR    "\pGoodness knows what happened!"
  227.  
  228. #define SYNCHRONOUS        FALSE    /* for sound */
  229. #define    ASYNCHRONOUS    TRUE
  230.  
  231. #include "Safari II.proto.h"
  232.  
  233. /* this structure is used for each row.  There is one animal per row. */
  234. struct    rowStruct
  235. {
  236.     Rect    rect;        /* the rect the animal is in (into which the bitmap is drawn */
  237.     Boolean    running;    /* is there an animal running in the row? */
  238.     int        animal;        /* what type of animal is it? */
  239.     int        speed;        /* how fast does it go? */
  240.     int        step;        /* alternates each pass so that different animal positions are
  241.                             drawn, creating the illusion of a stride */
  242. };
  243. struct    rowStruct    row[21]; /* Even if you have a really big Mac screen you can't have more than 21 rows of animals */
  244.  
  245. /* unusual variable names in comments */
  246.  
  247. /* increaseSpeed is true when the Game Options dialog has the speed of the game increase
  248.       as the score increases to the score.
  249.     easyShoot allows the player to score by shooting in a rect surrounding the animal
  250.       and does not require them to shoot directly within the outline of the animal
  251.       (good for kids) */
  252. Boolean    gDone, gWNEImplemented, gamePaused, gameOver, increaseSpeed, easyShoot, standardWindow, showHighScores;
  253. EventRecord    gTheEvent;
  254. MenuHandle    gAppleMenu, gFileMenu, gEditMenu;
  255. Rect    gDragRect, offScreenRect, whereAnimalsRun; /* whereAnimalsRun is the rect where animation occurs */
  256. int    gNewWindowLeft = WINDOW_HOME_LEFT, gNewWindowTop = WINDOW_HOME_TOP;
  257. int    windowHeight, windowWidth, noOfTicks, lastTicks;
  258.  
  259. /* animalValue is the point value of the animal.  
  260.    anRegion is a two dimention array with
  261.       two regions for each animal. One for each stride position.  The rgns are used to check
  262.       if someone has clicked directly inside the region.
  263.    loopValue keeps track of a group of statements which mimic a for loop, but which
  264.       increment only once every pass through the animation procedure.  This is done
  265.       instead of a for loop so that the game can respond to an event after each animal
  266.       is drawn.  
  267.    gameType tells if the game ends after a period of time, or after a given number of animals escape 
  268.    speedFactor and speedIncrease regulate the initial speed of the game and the increase
  269.        in speed as game play continues*/
  270. int    gameScore, animalsEscaped, animalRows, animalSpeed[11], animalValue[11];
  271. int    anRegion[11][2], loopValue, gameType, maxTime, speedFactor,speedIncrease;
  272. long maxEscaped, timeRemaining, lastTime, topScores[4];
  273. Rect    animalRect[11][2];
  274.  
  275. PicHandle    animalPicture;
  276. WindowPtr    gameWindow;
  277. GrafPtr   offscreen;
  278. ControlHandle    playAgainControl, quitControl;
  279. Str255        preferenceString[8], name, highScoreName[4];
  280.  
  281. SndChannelPtr    chanPtr;
  282.  
  283. /**** main ****/
  284. main (void)
  285. {
  286.     ToolBoxInit ();
  287.     
  288.     SetUpFirstGlobals();
  289.     
  290.     MenuBarInit();
  291.     WindowInit();
  292.     SetUpDragRect();
  293.     
  294.     InitOffscreen();
  295.     LoadInResources();
  296.     SetUpGame();
  297.     IntroDialog();
  298.  
  299.     MainLoop();
  300. }
  301.  
  302. /**** ToolBoxInit ****/
  303. ToolBoxInit (void)
  304. {
  305.     InitGraf( &thePort );
  306.     InitFonts();
  307.     InitWindows();
  308.     InitMenus();
  309.     TEInit();
  310.     InitDialogs( NIL_POINTER );
  311.     InitCursor();
  312.     MaxApplZone();
  313.     MoreMasters();
  314.     MoreMasters();
  315.     MoreMasters();
  316.     MoreMasters();
  317.     FlushEvents( everyEvent, REMOVE_ALL_EVENTS);
  318. }
  319.  
  320. /*** SetUpFirstGlobals ***/
  321. SetUpFirstGlobals(void)
  322. {    
  323.     DialogPtr    theDialog;
  324.  
  325.     showHighScores = TRUE;
  326.     /* DialogInit() requires that the Dialog be created since it calls the DITL,
  327.         so we create the dialog, call the procedure, and dispose of the dialog
  328.         without ever displaying the dialog */
  329.     if (( theDialog = GetNewDialog( GAME_OPTIONS_DIALOG, NIL_POINTER, M_T_F)) 
  330.             == NIL_POINTER)
  331.         ErrorHandler( NO_WIND);
  332.     lastTicks = TickCount();
  333.     DialogInit(theDialog, GAME_OPTIONS_DIALOG);
  334.     DisposDialog(theDialog);
  335. }
  336.  
  337. /**** MenuBarInit ****/
  338. MenuBarInit(void)
  339. {
  340.     Handle    myMenuBar;
  341.     
  342.     if ( ( myMenuBar = GetNewMBar( BASE_RES_ID )) == NIL_POINTER ) 
  343.             ErrorHandler (NO_MBAR);
  344.     SetMenuBar( myMenuBar );
  345.     if ( ( gAppleMenu = GetMHandle ( APPLE_MENU_ID )) == NIL_POINTER )
  346.             ErrorHandler (NO_MENU);
  347.     AddResMenu( gAppleMenu, 'DRVR');
  348.     if ( ( gEditMenu = GetMHandle ( EDIT_MENU_ID )) == NIL_POINTER )
  349.         ErrorHandler( NO_MENU );
  350.     if ( ( gFileMenu = GetMHandle ( FILE_MENU_ID )) == NIL_POINTER )
  351.         ErrorHandler( NO_MENU );
  352.         
  353.     DrawMenuBar ();
  354. }
  355.  
  356. WindowInit(void)
  357. {
  358.     if (( gameWindow = GetNewWindow( BASE_RES_ID, NIL_POINTER, M_T_F)) 
  359.             == NIL_POINTER)
  360.         ErrorHandler( NO_WIND);
  361.         
  362.     playAgainControl = GetNewControl(PLAY_AGAIN_BUTTON, gameWindow);
  363.     quitControl = GetNewControl(QUIT_BUTTON, gameWindow);
  364. }
  365.  
  366. /** CenterWindow **/
  367. CenterWindow (WindowPtr theWindow)
  368. {
  369.     int    newLeft, newTop;
  370.     Rect    theRect, gScreenRect;
  371.     
  372.     theRect = theWindow->portRect;
  373.     gScreenRect = screenBits.bounds;
  374.     
  375.     newLeft = ((gScreenRect.right - gScreenRect.left) - (theRect.right - theRect.left))/2;
  376.     newTop = ((gScreenRect.bottom - (gScreenRect.top + MBarHeight + TITLE_BAR_HEIGHT)) 
  377.         - (theRect.bottom - theRect.top))/2;
  378.     MoveWindow (theWindow, newLeft, newTop+MBarHeight+TITLE_BAR_HEIGHT, BRING_TO_FRONT);
  379.     ShowWindow(theWindow);
  380. }
  381.  
  382. /*** AdjustWindowSize ***/
  383. AdjustWindowSize(void)
  384. {
  385.     Rect    windowRect;
  386.     int    length, h, v;
  387.     
  388.     SetPort( gameWindow);
  389.     
  390.     if (!(standardWindow)) /* if it's not the 9" screen window, then */
  391.     {
  392.         SizeWindow(gameWindow,
  393.                 screenBits.bounds.right - BORDER, 
  394.                 screenBits.bounds.bottom - (MBarHeight + BORDER + TITLE_BAR_HEIGHT),
  395.                 TRUE);
  396.     }
  397.     else
  398.         SizeWindow(gameWindow, 506, 298, TRUE);
  399.     
  400.     windowRect = gameWindow->portRect;
  401.     
  402.     windowWidth = windowRect.right - windowRect.left;
  403.     windowHeight = windowRect.bottom - windowRect.top;
  404.     
  405.     CenterWindow(gameWindow);
  406.     TextFont( systemFont);
  407.     
  408.     v = windowHeight/2 + 20;
  409.     h = windowWidth/2 - 100;
  410.     MoveControl(playAgainControl, h, v);
  411.     
  412.     h = windowWidth/2 + 20;
  413.     MoveControl(quitControl, h, v);
  414. }
  415.  
  416. /**** CreateOffscreenBitMap (borrowed from Apple TN#41) ****/
  417. Boolean CreateOffscreenBitMap(GrafPtr *newOffscreen, Rect *inBounds)
  418. {
  419.   GrafPtr savePort;
  420.   GrafPtr newPort;
  421.  
  422.   GetPort(&savePort);    /* need this to restore thePort after OpenPort */
  423.  
  424.   newPort = (GrafPtr) NewPtr(sizeof(GrafPort));    /* allocate the grafPort */
  425.   if (MemError() != noErr)
  426.     return false;                 /* failed to allocate the off-screen port */
  427.   /*
  428.   the call to OpenPort does the following . . . 
  429.     allocates space for visRgn (set to screenBits.bounds) and clipRgn (set wide open)
  430.     sets portBits to screenBits
  431.     sets portRect to screenBits.bounds
  432.     etc. (see IM I-163,164)
  433.     side effect: does a SetPort(&offScreen)
  434.   */
  435.   OpenPort(newPort);
  436.   /* make bitmap the size of the bounds that caller supplied */
  437.   newPort->portRect = *inBounds;
  438.   newPort->portBits.bounds = *inBounds;
  439.   RectRgn(newPort->clipRgn, inBounds);    /* avoid wide-open clipRgn, to be safe  */
  440.   RectRgn(newPort->visRgn, inBounds);     /* in case newBounds is > screen bounds */
  441.  
  442.   /* rowBytes is size of row, it must be rounded up to an even number of bytes */
  443.   newPort->portBits.rowBytes = ((inBounds->right - inBounds->left + 15) >> 4) << 1;
  444.  
  445.   /* number of bytes in BitMap is rowBytes * number of rows */
  446.   /* see notes at end of Technical Note about using _NewHandle rather than _NewPtr */
  447.   newPort->portBits.baseAddr =
  448.            NewPtr(newPort->portBits.rowBytes * (long) (inBounds->bottom - inBounds->top));
  449.   if (MemError()!=noErr) {   /* check to see if we had enough room for the bits */
  450.     SetPort(savePort);
  451.     ClosePort(newPort);      /* dump the visRgn and clipRgn */
  452.     DisposPtr((Ptr)newPort); /* dump the GrafPort */
  453.     return false;            /* tell caller we failed */
  454.     }
  455.   /* since the bits are just memory, let's clear them before we start */
  456.   EraseRect(inBounds);     /* OpenPort did a SetPort(newPort) so we are ok */
  457.   *newOffscreen = newPort;
  458.   SetPort(savePort);
  459.   return true;               /* tell caller we succeeded! */
  460. }
  461.  
  462. /**** DestroyOffscreenBitMap (TN#41) ****/
  463. void DestroyOffscreenBitMap(GrafPtr oldOffscreen)
  464. {
  465.   ClosePort(oldOffscreen);                       /* dump the visRgn and clipRgn */
  466.   DisposPtr(oldOffscreen->portBits.baseAddr);    /* dump the bits */
  467.   DisposPtr((Ptr)oldOffscreen);                  /* dump the port */
  468. }
  469.  
  470. /**** InitOffscreen ****/
  471. InitOffscreen(void)
  472. {    
  473.     SetRect(&offScreenRect, 0,0,227, 151); /* This is how big the Rect of ANIMAL_PICTURE is */
  474.  
  475.     if (!CreateOffscreenBitMap(&offscreen, &offScreenRect)) 
  476.     {
  477.         SysBeep(1);
  478.         ExitToShell();
  479.     }
  480.     
  481.     animalPicture = GetPicture ( ANIMAL_PICTURE);
  482.     SetPort (offscreen);
  483.     DrawPicture(animalPicture, &offScreenRect);
  484.     SetPort(gameWindow);
  485. }
  486.  
  487. /*** LoadInResources ***/
  488. LoadInResources(void)
  489. {
  490.     /* do this at the beginning of the program, so that all resources are in memory.
  491.        if you don't do this, the resources will be loaded in each time they're accessed and
  492.        you'll notice the performance degrade when you first click on an animal and you
  493.        access the rgns or sound for that animal */
  494.     int            i;
  495.     RgnHandle    theRgn;
  496.     Handle        theSnd;
  497.     
  498.     for (i=400; i<=417; ++i)
  499.     {
  500.         if (( theRgn = (RgnHandle) GetResource( 'RGN ', i) ) 
  501.                 == NIL_POINTER)
  502.             ErrorHandler( NO_RGN);
  503.     }
  504.     
  505.     for (i=401; i<=412; ++i)
  506.     {
  507.         if (( theSnd = GetResource('snd ', i) ) 
  508.                 == NIL_POINTER)
  509.             ErrorHandler( CANT_LOAD_SND);
  510.     }
  511. }
  512.  
  513. /**** SetUpDragRect ****/
  514. SetUpDragRect(void)
  515. {
  516.     gDragRect = screenBits.bounds;
  517.     gDragRect.left +=DRAG_THRESHOLD;
  518.     gDragRect.right -=DRAG_THRESHOLD;
  519.     gDragRect.bottom -=DRAG_THRESHOLD;
  520. }
  521.  
  522. /*** SetUpGame ***/
  523. SetUpGame(void)
  524. {
  525.     int    i;
  526.     long    stringValue;
  527.     Str255    myString;
  528.     Rect    offRect, onRect, windowRect;
  529.     DialogPtr    theDialog;
  530.     
  531.     SetPreferences(); /* gets the current game settings */
  532.     if (showHighScores)
  533.         GetHighScores();
  534.     AdjustWindowSize();
  535.     HideControl(playAgainControl);
  536.     HideControl(quitControl);
  537.  
  538.     SetRect(&windowRect, 0, 0, windowWidth, windowHeight);
  539.     EraseRect(&windowRect);
  540.     speedIncrease = 0;
  541.     
  542.     /* Rhino */
  543.     SetRect(&animalRect[1][1], 2, 2, 35, 35);
  544.     SetRect(&animalRect[1][2], 40, 2, 73, 35);
  545.         
  546.     /* Elephant */
  547.     SetRect(&animalRect[2][1], 2, 40, 35, 73);
  548.     SetRect(&animalRect[2][2], 40, 40, 73, 73);
  549.         
  550.     /* Zebra */
  551.     SetRect(&animalRect[3][1], 2, 78, 35, 111);
  552.     SetRect(&animalRect[3][2], 40, 78, 73, 111);
  553.  
  554.     /* Gorrilla */
  555.     SetRect(&animalRect[4][1], 2, 116, 35, 149);
  556.     SetRect(&animalRect[4][2], 40, 116, 73, 149);
  557.     
  558.     /* Antelope */
  559.     SetRect(&animalRect[5][1], 78, 2, 111, 35);
  560.     SetRect(&animalRect[5][2], 116, 2, 149, 35);
  561.     
  562.     /* Giraffe */
  563.     SetRect(&animalRect[6][1], 78, 40, 111, 73);
  564.     SetRect(&animalRect[6][2], 116, 40, 149, 73);
  565.         
  566.     /* Lion */
  567.     SetRect(&animalRect[7][1], 78, 78, 111, 111);
  568.     SetRect(&animalRect[7][2], 116, 78, 149, 111);
  569.     
  570.     /* Cheetah */
  571.     SetRect(&animalRect[8][1], 78, 116, 111, 149);
  572.     SetRect(&animalRect[8][2], 116, 116, 149, 149);
  573.     
  574.     /* Warthog */
  575.     SetRect(&animalRect[9][1], 154, 2, 187, 35);
  576.     SetRect(&animalRect[9][2], 192, 2, 225, 35);
  577.     
  578.     /* Set Animal Values */
  579.     
  580.     animalValue[RHINO] = 10;
  581.     animalSpeed[RHINO] = 2;
  582.     
  583.     animalValue[ELEPHANT] = 10;
  584.     animalSpeed[ELEPHANT] = 2;
  585.     
  586.     animalValue[ZEBRA] = 60;
  587.     animalSpeed[ZEBRA] = 4;
  588.     
  589.     animalValue[GORILLA] = 50;
  590.     animalSpeed[GORILLA] = 3;
  591.     
  592.     animalValue[ANTELOPE] = 75;
  593.     animalSpeed[ANTELOPE] = 5;
  594.     
  595.     animalValue[GIRAFFE] = 60;
  596.     animalSpeed[GIRAFFE] = 4;
  597.     
  598.     animalValue[LION] = 75;
  599.     animalSpeed[LION] = 5;
  600.     
  601.     animalValue[CHEETAH] = 80;
  602.     animalSpeed[CHEETAH] = 6;
  603.         
  604.     animalValue[WARTHOG] = 60;
  605.     animalSpeed[WARTHOG] = 4;
  606.     
  607.     anRegion[RHINO][1] = 400;
  608.     anRegion[RHINO][2] = 401;
  609.     
  610.     anRegion[ELEPHANT][1] = 402;
  611.     anRegion[ELEPHANT][2] = 403;
  612.     
  613.     anRegion[ZEBRA][1] = 404;
  614.     anRegion[ZEBRA][2] = 405;
  615.     
  616.     anRegion[GORILLA][1] = 406;
  617.     anRegion[GORILLA][2] = 407;
  618.  
  619.     anRegion[ANTELOPE][1] = 408;
  620.     anRegion[ANTELOPE][2] = 409;
  621.     
  622.     anRegion[GIRAFFE][1] = 410;
  623.     anRegion[GIRAFFE][2] = 411;
  624.     
  625.     anRegion[LION][1] = 412;
  626.     anRegion[LION][2] = 413;
  627.     
  628.     anRegion[CHEETAH][1] = 414;
  629.     anRegion[CHEETAH][2] = 415;
  630.     
  631.     anRegion[WARTHOG][1] = 416;
  632.     anRegion[WARTHOG][2] = 417;
  633.     
  634.     gameScore = 0;
  635.     
  636.     if (gameType == ESCAPED_GAME)
  637.         animalsEscaped = 0;
  638.     else
  639.     {
  640.         StringToNum(&(preferenceString[MINUTES]),&stringValue);
  641.         timeRemaining = stringValue * 60;
  642.         StringToNum(&(preferenceString[SECONDS]),&stringValue);
  643.         timeRemaining += stringValue;
  644.         GetDateTime(&lastTime);
  645.     }
  646.     
  647.     DrawScoreBar();
  648.     
  649.     SetRect(&whereAnimalsRun, 0, 20, windowWidth, windowHeight);
  650.         
  651.     animalRows = (windowHeight-20)/33;
  652.     
  653.     if (animalRows >20)
  654.         animalRows =20;
  655.             
  656.     for (i=1; i <= animalRows; ++i)
  657.     {
  658.         SetRect(&row[i].rect, 0, (33*(i-1))+20, 33, (33*(i-1))+53);
  659.         row[i].running = FALSE;
  660.     }
  661.     loopValue = 1;
  662.     gamePaused = FALSE;
  663.     gameOver = FALSE;
  664.     
  665. }
  666.  
  667. /*** SetPreferences ***/
  668. SetPreferences(void)
  669. {
  670.     int    i;
  671.     long    currentSetting;
  672.     
  673.     for( i=0; i<=5; ++i)
  674.     {
  675.         StringToNum(&(preferenceString[i]),¤tSetting);
  676.         switch (currentSetting)
  677.         {
  678.             case TIMED_RADIO:
  679.                 gameType = TIMED_GAME;
  680.                 break;
  681.             case ESCAPED_RADIO:
  682.                 gameType = ESCAPED_GAME;
  683.                 break;
  684.             case NINE_INCH_RADIO:
  685.                 standardWindow = TRUE;
  686.                 break;
  687.             case CURRENT_SCREEN_RADIO:
  688.                 standardWindow = FALSE;
  689.                 break;
  690.             case INCREASE_YES_RADIO:
  691.                 increaseSpeed = TRUE;
  692.                 break;
  693.             case INCREASE_NO_RADIO:
  694.                 increaseSpeed = FALSE;
  695.                 break;
  696.             case SLOW_RADIO:
  697.                 speedFactor = 1;
  698.                 break;
  699.             case MEDIUM_RADIO:
  700.                 speedFactor = 4;
  701.                 break;
  702.             case FAST_RADIO:
  703.                 speedFactor = 5;
  704.                 break;
  705.             case IN_ANIMAL_OUTLINE_RADIO:
  706.                 easyShoot = FALSE;
  707.                 break;
  708.             case IN_BOX_SURROUNDING_ANIMAL_RADIO:
  709.                 easyShoot = TRUE;
  710.                 break;
  711.         }
  712.     }
  713.     StringToNum(&(preferenceString[MAX_ESCAPED]),&maxEscaped);
  714. }
  715.  
  716.     
  717. /*** GetHighScores ***/
  718. GetHighScores(void)
  719. {
  720.     int    i;
  721.     StringHandle    theString;
  722.                 
  723.     for (i=0; i<=2; ++i)
  724.     {
  725.         if ( ( theString = GetString( i + HIGH_SCORE_STRING ) ) == NIL_POINTER )
  726.             ErrorHandler(NO_STR);
  727.         MoveHHi((Handle)theString);
  728.         HLock((Handle)theString);    
  729.         StringToNum(*theString,&topScores[(i+1)]);
  730.         HUnlock((Handle)theString);
  731.     }
  732. }
  733.  
  734. /*** DrawScoreBar ***/
  735. DrawScoreBar(void)
  736. {
  737.     Str255    scoreString;
  738.     int        length;
  739.     Rect    theRect;
  740.     
  741.     SetRect(&theRect, 0, 0, windowWidth, 20);
  742.     EraseRect(&theRect);
  743.     MoveTo(2,17);
  744.     DrawString("\pScore: ");
  745.     NumToString(gameScore, scoreString);
  746.     DrawString(scoreString);
  747.  
  748.     if (showHighScores)
  749.         PostHighScore();
  750.     
  751.     if (gameType == ESCAPED_GAME)
  752.     {
  753.         length = StringWidth("\pAnimals Escaped: 500") +2;
  754.         MoveTo(windowWidth - length, 17);
  755.         NumToString(animalsEscaped, scoreString);
  756.         DrawString("\pAnimals Escaped: ");
  757.         DrawString(scoreString);
  758.     } else
  759.     {
  760.         length = StringWidth("\pTime Remaining: 00:00") +2;
  761.         MoveTo(windowWidth - length, 17);
  762.         DrawString("\pTime Remaining: ");
  763.         PostTimeRemaining();
  764.     }
  765. }
  766.  
  767. /*** PostTimeRemaining ***/
  768. PostTimeRemaining(void)
  769. {
  770.     long    diffTime, currentTime;
  771.     int        mins, secs, length;
  772.     Str255    timeString;
  773.     Rect    timeRect;
  774.     
  775.     GetDateTime(¤tTime);
  776.     diffTime = currentTime - lastTime;
  777.     if (diffTime > 0)
  778.     {
  779.         length = StringWidth("\p00:00") +2;
  780.         SetRect(&timeRect, windowWidth - length, 0, windowWidth, 17);
  781.         EraseRect(&timeRect);
  782.         MoveTo(windowWidth - length, 17);
  783.         timeRemaining -= diffTime;
  784.         if(timeRemaining > 0)
  785.         {
  786.             mins = timeRemaining/60;
  787.             NumToString(mins,timeString);
  788.             DrawString(timeString);
  789.             DrawString("\p:");
  790.             secs = timeRemaining - mins*60;
  791.             if ((secs <= 9) && (secs >= 0))
  792.                 DrawString("\p0");
  793.             NumToString(secs, timeString);
  794.             DrawString(timeString);
  795.         }
  796.         else
  797.         {
  798.             DrawString("\p0:00");
  799.             EndGame();
  800.         }
  801.     }
  802.     GetDateTime(&lastTime);
  803. }
  804.  
  805. /*** PostHighScore ***/
  806. PostHighScore(void)
  807. {
  808.     long            i;
  809.     int                length;
  810.     Str255            myString;
  811.     StringHandle    theString;
  812.     
  813.     length = StringWidth("\pHigh Score: ") +2;
  814.         
  815.     if ( ( theString = GetString( HIGH_SCORE_STRING ) ) == NIL_POINTER )
  816.         ErrorHandler(NO_STR);
  817.     MoveHHi((Handle)theString);
  818.     HLock((Handle)theString);
  819.     
  820.     StringToNum(*theString,&i);
  821.     NumToString( i, myString);
  822.     
  823.     length += StringWidth (myString);
  824.     MoveTo((windowWidth-length)/2, 17);
  825.     DrawString("\pHigh Score: ");
  826.     DrawString(myString);
  827.     
  828.     HUnlock((Handle)theString);
  829. }
  830.  
  831. /**** MainLoop ****/
  832. MainLoop(void)
  833. {
  834.     
  835.     gDone = FALSE;
  836.     gWNEImplemented = ( NGetTrapAddress( WNE_TRAP_NUM, ToolTrap ) 
  837.             != NGetTrapAddress( UNIMPL_TRAP_NUM, ToolTrap ) );
  838.     while (gDone == FALSE)
  839.     {
  840.             HandleEvent();
  841.             
  842.             if ( (!(gamePaused)) && (!(gameOver)) )
  843.             {
  844.                 noOfTicks = TickCount();
  845.                 if ( (noOfTicks - lastTicks) >= TICK_DELAY)
  846.                 {
  847.                     Animate();
  848.                     lastTicks = TickCount();
  849.                 }
  850.             }
  851.     }
  852. }
  853.  
  854. /**** HandleEvent ****/
  855. HandleEvent(void)
  856. {
  857.     char    theChar;
  858.     GrafPtr    oldPort;
  859.     WindowPtr    window;
  860.  
  861.     
  862.     if (gWNEImplemented )
  863.         WaitNextEvent( everyEvent, &gTheEvent, MIN_SLEEP, NIL_MOUSE_REGION );
  864.     else
  865.     {
  866.         SystemTask ();
  867.         GetNextEvent( everyEvent, &gTheEvent );
  868.     }
  869.     
  870.     AdjustCurosr(gTheEvent.where);
  871.     
  872.     switch (gTheEvent.what)
  873.     {
  874.         case mouseDown:
  875.             HandleMouseDown();
  876.             break;
  877.         case keyDown:
  878.         case autoKey:
  879.             theChar = gTheEvent.message & charCodeMask;
  880.             if (( gTheEvent.modifiers & cmdKey ) != 0)
  881.             {
  882.                 AdjustMenus();
  883.                 HandleMenuChoice( MenuKey ( theChar ) );
  884.             }
  885.             break;
  886.         case updateEvt:
  887.             if (! IsDAWindow( (WindowPtr)gTheEvent.message ) )
  888.             {
  889.                 GetPort( &oldPort);
  890.                 SetPort( (GrafPtr)gTheEvent.message);
  891.                 
  892.                 BeginUpdate( (GrafPtr)gTheEvent.message);
  893.                 
  894.                 GetDateTime(&lastTime);
  895.                 window = FrontWindow();
  896.                 if (window == gameWindow )
  897.                 {
  898.                     DrawScoreBar();
  899.                     if (gameOver || gamePaused )
  900.                         DrawContent();
  901.                     if (gameOver)
  902.                         WriteGameOver();
  903.                     DrawControls(gameWindow);
  904.                 }
  905.                 EndUpdate( (GrafPtr)gTheEvent.message);
  906.                 SetPort(oldPort);
  907.             }
  908.             break;
  909.     }
  910. }
  911.  
  912. /*** AdjustCurosr ***/
  913. AdjustCurosr(Point mouse)
  914. {    
  915.     WindowPtr    window;
  916.     
  917.     window = FrontWindow();
  918.     
  919.     if (window != gameWindow )
  920.     {
  921.         SetCursor(&arrow);
  922.         return;
  923.     }
  924.     
  925.     GlobalToLocal(&mouse);
  926.     
  927.     if ( PtInRect(mouse, &whereAnimalsRun) )
  928.         SetCursor( *GetCursor(CROSSHAIR) );
  929.     else
  930.         SetCursor(&arrow);
  931. }
  932.  
  933. /**** HandleMouseDown ****/
  934. HandleMouseDown(void)
  935. {
  936.     WindowPtr    whichWindow;
  937.     short int    thePart;
  938.     long int    menuChoice, windSize;
  939.     
  940.     thePart = FindWindow( gTheEvent.where, &whichWindow );
  941.     switch( thePart )
  942.     {
  943.         case inMenuBar:
  944.             AdjustMenus();
  945.             menuChoice = MenuSelect( gTheEvent.where);
  946.             HandleMenuChoice( menuChoice );
  947.             break;
  948.         case inSysWindow:
  949.             SystemClick( &gTheEvent, whichWindow);
  950.             break;
  951.         case inDrag:
  952.             DragWindow( whichWindow, gTheEvent.where, &gDragRect);
  953.             break;
  954.         case inContent:
  955.             SelectWindow( whichWindow);
  956.             if ( (!(gamePaused)) && (!(gameOver)) )
  957.                 HandleInContent( gTheEvent.where);
  958.             if (gameOver)
  959.                 HandleGameOverButtons(gTheEvent.where);
  960.             break;
  961.     }
  962. }
  963.  
  964. /**** AdjustMenus ****/
  965. AdjustMenus(void)
  966. {
  967.     if ( IsDAWindow( FrontWindow() ) )
  968.     {
  969.         EnableItem( gEditMenu, UNDO_ITEM);
  970.         EnableItem( gEditMenu, CUT_ITEM);
  971.         EnableItem( gEditMenu, PASTE_ITEM);
  972.         EnableItem( gEditMenu, COPY_ITEM);
  973.         EnableItem( gEditMenu, CLEAR_ITEM);
  974.     }
  975.     else
  976.     {
  977.         DisableItem( gEditMenu, UNDO_ITEM);
  978.         DisableItem( gEditMenu, CUT_ITEM);
  979.         DisableItem( gEditMenu, PASTE_ITEM);
  980.         DisableItem( gEditMenu, COPY_ITEM);
  981.         DisableItem( gEditMenu, CLEAR_ITEM);
  982.     }
  983.     
  984.     if (gameOver)
  985.     {
  986.         DisableItem( gFileMenu, PAUSE_RESUME_ITEM);
  987.         DisableItem( gFileMenu, STOP_ITEM);
  988.     }
  989.     else
  990.     {
  991.         EnableItem( gFileMenu, PAUSE_RESUME_ITEM);
  992.         EnableItem( gFileMenu, STOP_ITEM);        
  993.     }
  994.     if ((gamePaused))
  995.     {
  996.         SetItem(gFileMenu, PAUSE_RESUME_ITEM, "\pResume");
  997.     } else
  998.     {
  999.         SetItem(gFileMenu, PAUSE_RESUME_ITEM, "\pPause");
  1000.     }        
  1001. }
  1002.  
  1003. /**** IsDAWindow ****/
  1004. IsDAWindow(WindowPtr whichWindow)
  1005. {
  1006.     if ( whichWindow == NIL_POINTER)
  1007.         return ( FALSE);
  1008.     else
  1009.         return( ( (WindowPeek)whichWindow)->windowKind < 0);
  1010. }
  1011.  
  1012. /**** HandleMenuChoice ****/
  1013. HandleMenuChoice(long int menuChoice)
  1014. {
  1015.     int    theMenu;
  1016.     int    theItem;
  1017.     
  1018.     if( menuChoice != 0 )
  1019.     {
  1020.         theMenu = HiWord( menuChoice );
  1021.         theItem = LoWord( menuChoice );
  1022.         switch ( theMenu)
  1023.         {
  1024.             case APPLE_MENU_ID:
  1025.                 HandleAppleChoice( theItem );
  1026.                 break;
  1027.             case FILE_MENU_ID:
  1028.                 HandleFileChoice( theItem );
  1029.             case EDIT_MENU_ID:
  1030.                 HandleEditChoice( theItem);
  1031.                 break;
  1032.             case GAME_MENU_ID:
  1033.                 HandleGameChoice( theItem);
  1034.                 break;
  1035.         }
  1036.         HiliteMenu( 0 );
  1037.     }
  1038. }
  1039.  
  1040. /**** HandleAppleChoice ****/
  1041. HandleAppleChoice(int theItem)
  1042. {
  1043.     Str255    accName;
  1044.     int    accNumber;
  1045.     GrafPtr    oldPort;
  1046.     
  1047.     switch( theItem )
  1048.     {
  1049.         case ABOUT_ITEM:
  1050.             AboutDialog();
  1051.             break;
  1052.         default :
  1053.             GetItem( gAppleMenu, theItem, accName);
  1054.             GetPort(&oldPort);
  1055.             accNumber = OpenDeskAcc( accName);
  1056.             SetPort(oldPort);
  1057.             break;
  1058.     }
  1059. }
  1060.  
  1061. /**** HandleFileChoice ****/
  1062. HandleFileChoice(int theItem)
  1063. {
  1064.     WindowPtr    whichWindow;
  1065.     switch    ( theItem)
  1066.     {
  1067.         case NEW_GAME_ITEM:
  1068.             SetUpGame();
  1069.             break;
  1070.         case PAUSE_RESUME_ITEM:
  1071.             /* Handle Pause/Resume Selection */
  1072.             if (!(gamePaused))
  1073.             {
  1074.                 gamePaused= TRUE;
  1075.             } else
  1076.             {
  1077.                 gamePaused= FALSE;        
  1078.                 GetDateTime(&lastTime);
  1079.             }        
  1080.             break;
  1081.         case STOP_ITEM:
  1082.             EndGame();
  1083.             break;
  1084.         case QUIT_ITEM:
  1085.             gDone = TRUE;
  1086.             break;
  1087.     }
  1088. }
  1089.  
  1090. /**** HandleEditChoice ****/
  1091. HandleEditChoice (int theItem)
  1092. {
  1093.     SystemEdit( theItem - 1);
  1094. }
  1095.  
  1096. /**** HandleGameChoice ****/
  1097. HandleGameChoice(int theItem)
  1098. {
  1099.     WindowPtr    whichWindow;
  1100.     switch    ( theItem)
  1101.     {
  1102.         case GAME_OPTIONS_ITEM:
  1103.             GameOptionsDialog(GAME_OPTIONS_DIALOG);
  1104.             break;
  1105.         case ANIMAL_POINT_VALUES_ITEM:
  1106.             AnimalPointValuesDialog();
  1107.             break;
  1108.         case HALL_OF_FAME_ITEM:
  1109.             HallOfFameDialog();
  1110.             break;
  1111.     }
  1112. }
  1113.  
  1114. /*** HandleInContent ***/
  1115. HandleInContent(Point mouse)
  1116. {
  1117.     int    i, h, v;
  1118.     RgnHandle    animalRgn;
  1119.     Str255    mySound;
  1120.     
  1121.     GlobalToLocal(&mouse);
  1122.     
  1123.     for (i = 1; i <= animalRows; ++i)
  1124.     {
  1125.         if ( PtInRect ( mouse, &row[i].rect) )
  1126.         {
  1127.             if (!(easyShoot))
  1128.             {
  1129. /*                animalRgn = NewRgn(); */
  1130.                 animalRgn = (RgnHandle) GetResource( 'RGN ', anRegion[row[i].animal][row[i].step]);
  1131.                 
  1132.                 h = row[i].rect.right - (**animalRgn).rgnBBox.right;
  1133.                 v = row[i].rect.bottom - (**animalRgn).rgnBBox.bottom;
  1134.             
  1135.                 OffsetRgn(animalRgn, h, v);
  1136.                 
  1137.                 if (PtInRgn( mouse, animalRgn)) 
  1138.                 {
  1139.                     PaintRgn(animalRgn);
  1140.                     DoTheSound( BASE_RES_ID + row[i].animal, TRUE );
  1141.                     AnimalShot(i);
  1142.                 }
  1143.             }    
  1144.             else
  1145.             {
  1146.                 DoTheSound( BASE_RES_ID + row[i].animal, TRUE );
  1147.                 AnimalShot(i);
  1148.             }    
  1149.         }
  1150.     }
  1151. }
  1152.  
  1153. /*** HandleGameOverButtons ***/
  1154. HandleGameOverButtons(Point mouse)
  1155. {
  1156.     int                partCode, inButton;
  1157.     ControlHandle    whichControl;
  1158.     
  1159.     GlobalToLocal(&mouse);
  1160.     
  1161.     partCode = FindControl(mouse, gameWindow, &whichControl);
  1162.     
  1163.     if (whichControl != NIL_POINTER)
  1164.     {
  1165.         inButton = TrackControl(whichControl, mouse, NIL_POINTER);
  1166.         if (inButton != 0)
  1167.         {
  1168.             if ( whichControl == playAgainControl )
  1169.                 SetUpGame();
  1170.             if (whichControl == quitControl)
  1171.                 ExitToShell();
  1172.         }
  1173.     }
  1174. }
  1175.  
  1176. /*** AnimalShot ***/
  1177. AnimalShot(int i)
  1178. {
  1179.     Str255    scoreString;
  1180.     int        length;
  1181.     Rect    scoreRect;
  1182.     
  1183.     gameScore = gameScore + animalValue[row[i].animal];
  1184.     length = StringWidth("\pScore: ")+2;
  1185.     SetRect(&scoreRect, length, 0, length + StringWidth("\p000000"), 20);
  1186.     EraseRect(&scoreRect);
  1187.     MoveTo(length, 17);
  1188.     NumToString(gameScore, scoreString);
  1189.     DrawString(scoreString);
  1190.         
  1191.     EraseRect(&row[i].rect);
  1192.     row[i].rect.left = 0;
  1193.     row[i].rect.right = 33;
  1194.        row[i].running = FALSE;
  1195.        
  1196.        if (increaseSpeed)
  1197.         speedIncrease = gameScore/1000;
  1198. }
  1199.  
  1200. /**** ErrorHandler ****/
  1201. ErrorHandler(int stringNum)
  1202. {
  1203.     StringHandle    errorStringH;
  1204.     
  1205.     if ( ( errorStringH = GetString( stringNum ) ) == NIL_POINTER )
  1206.         ParamText( HOPELESSLY_FATAL_ERROR, NIL_STRING, NIL_STRING, NIL_STRING);
  1207.     else
  1208.     {
  1209.         MoveHHi((Handle)errorStringH);
  1210.         HLock( (Handle)errorStringH);
  1211.         ParamText( *errorStringH, NIL_STRING, NIL_STRING, NIL_STRING);
  1212.         HUnlock( (Handle)errorStringH);
  1213.     }
  1214.     StopAlert( ERROR_ALERT_ID, NIL_POINTER);
  1215.     ExitToShell();
  1216. }
  1217.  
  1218. /*** Animate ***/
  1219. Animate(void)
  1220. {    int    i, r;
  1221.     Rect    copyRect;
  1222.     GrafPtr   secondOffScreen;
  1223.     
  1224.     /* Open loop - goes from 1 to animalRows & allows for WaitNextEvent to occur
  1225.         between each animal drawing */
  1226.     if (loopValue > animalRows )
  1227.         loopValue = 1;
  1228.     {        
  1229.         if (! (row[loopValue].running) )
  1230.         {
  1231.             row[loopValue].running = TRUE;
  1232.             do{
  1233.                 r = Randomize(10);
  1234.             }
  1235.             while (r<1 || r>9);
  1236.             row[loopValue].animal = r;
  1237.             row[loopValue].speed = animalSpeed[r];
  1238.             row[loopValue].step = 1;
  1239.         }
  1240.                 
  1241.         if (row[loopValue].step == 2)
  1242.             row[loopValue].step = 1;
  1243.         else
  1244.             row[loopValue].step = 2;
  1245.         
  1246.         OffsetRect(&row[loopValue].rect, 
  1247.                 row[loopValue].speed * speedFactor + speedIncrease, 0);
  1248.     
  1249.         SetRect(©Rect, row[loopValue].rect.left
  1250.             - (row[loopValue].speed * speedFactor + speedIncrease), row[loopValue].rect.top,
  1251.                 row[loopValue].rect.right, row[loopValue].rect.bottom);
  1252.  
  1253.         if (!CreateOffscreenBitMap(&secondOffScreen, ©Rect)) 
  1254.             {
  1255.                 SysBeep(1);
  1256.                 ExitToShell();
  1257.             }
  1258.            SetPort (secondOffScreen);
  1259.            EraseRect(©Rect);
  1260.            
  1261.            CopyBits(&offscreen->portBits, &secondOffScreen->portBits, 
  1262.                        &animalRect[row[loopValue].animal][row[loopValue].step], &row[loopValue].rect, srcCopy, 0L);
  1263.            SetPort (gameWindow);
  1264.            CopyBits(&secondOffScreen->portBits, &(*gameWindow).portBits,
  1265.                        ©Rect, ©Rect, srcCopy, 0L);
  1266.            DestroyOffscreenBitMap(secondOffScreen);
  1267.  
  1268.            if (row[loopValue].rect.left >= windowWidth)
  1269.            {
  1270.             row[loopValue].rect.left = 0;
  1271.             row[loopValue].rect.right = 33;
  1272.                row[loopValue].running = FALSE;
  1273.                if(gameType == ESCAPED_GAME)
  1274.                  AnimalEscaped();
  1275.            }
  1276.     }
  1277.     ++loopValue;
  1278.     if (gameType == TIMED_GAME)
  1279.         PostTimeRemaining();
  1280. }
  1281.  
  1282. /*** DrawContent ***/
  1283. DrawContent(void)
  1284. {    int    i, r;
  1285.     Rect    copyRect;
  1286.     GrafPtr   secondOffScreen;
  1287.     GrafPtr    oldPort;
  1288.     
  1289.     GetPort( &oldPort);
  1290.     SetPort( gameWindow);
  1291.  
  1292.     for (i = 1; i<= animalRows; ++i)
  1293.            CopyBits(&offscreen->portBits, &(*gameWindow).portBits,
  1294.                      &animalRect[row[i].animal][row[i].step], &row[i].rect,srcCopy, 0L);
  1295.     SetPort(oldPort);
  1296. }
  1297.  
  1298. /** Randomize **/
  1299.  Randomize (int range)
  1300.  {
  1301.      long    rawResult;
  1302.      rawResult = Random();
  1303.      if( rawResult < 0 ) rawResult *= -1;
  1304.      return( (rawResult * range)/32768);
  1305.  }
  1306.  
  1307.  /*** AnimalEscaped ***/
  1308.  AnimalEscaped(void)
  1309.  {
  1310.      Str255    scoreString;
  1311.     int        length;
  1312.     Rect    escapedRect;
  1313.         
  1314.     ++animalsEscaped;
  1315.     length = StringWidth("\p000") +2;
  1316.     SetRect(&escapedRect, windowWidth - length, 0, windowWidth, 20);
  1317.     MoveTo(windowWidth - length, 17);
  1318.     NumToString(animalsEscaped, scoreString);
  1319.     EraseRect(&escapedRect);
  1320.     DrawString(scoreString);
  1321.     if ( (gameType == ESCAPED_GAME) && (maxEscaped <= animalsEscaped) )
  1322.         EndGame();
  1323.  }
  1324.  
  1325.  
  1326. /*** DoTheSound ***/
  1327. DoTheSound(int whichOne, Boolean asynch)
  1328. {
  1329.     Handle    theSnd;
  1330.     OSErr    err, myErr;
  1331.  
  1332.     theSnd = GetResource('snd ', whichOne);
  1333.     MoveHHi((Handle)theSnd);
  1334.     HLock((Handle)theSnd);
  1335.     if ( theSnd != NIL_POINTER) 
  1336.     {
  1337.         if (chanPtr != NIL_POINTER)
  1338.             {
  1339.                 err = SndDisposeChannel(chanPtr, TRUE);
  1340.                 chanPtr = NIL_POINTER;
  1341.             }
  1342.             
  1343.         chanPtr = NIL_POINTER;
  1344.         
  1345.         myErr = SndNewChannel(&chanPtr, 0, 0, NIL_POINTER);
  1346.         
  1347.         if ( (asynch == TRUE) && (myErr == noErr) )
  1348.             err = SndPlay(chanPtr, theSnd, TRUE);
  1349.         else
  1350.             err = SndPlay(NIL_POINTER, theSnd, FALSE);
  1351.     }
  1352.     HUnlock((Handle)theSnd);
  1353. }
  1354.  
  1355. /*** WriteGameOver ***/
  1356. WriteGameOver(void)
  1357. {
  1358.     int    length, h, v;
  1359.     Rect    myRect;
  1360.     
  1361.     length = StringWidth("\pGame Over");
  1362.     SetRect(&myRect, windowWidth/2 - length/2 - 2, windowHeight/2 - 10 , 
  1363.             windowWidth/2 + length/2 + 2, windowHeight/2 + 10);
  1364.     EraseRect(&myRect);
  1365.     MoveTo(windowWidth/2 - length/2, windowHeight/2);
  1366.     DrawString("\pGame Over");
  1367. }
  1368.  
  1369. /*** EndOfGameControls ***/
  1370. EndOfGameControls(void)
  1371. {
  1372.     ShowControl(playAgainControl);
  1373.     ShowControl(quitControl);
  1374. }
  1375.  
  1376. /*** EndGame ***/
  1377. EndGame(void)
  1378. {
  1379.     gameOver = TRUE;
  1380.     WriteGameOver();
  1381.     EndOfGameControls();
  1382.     if ((gameScore >= topScores[3]) && (showHighScores))
  1383.         UpdateHighScores();
  1384. }
  1385.  
  1386. /*** UpdateHighScores ***/
  1387. UpdateHighScores(void)
  1388. {
  1389.     int                i;
  1390.     Str255            numString;
  1391.     StringHandle    theString, topNames[4];
  1392.     
  1393.     GetPlayerName();
  1394.     
  1395.     for (i=0; i<=2; ++i)
  1396.     {
  1397.         if ( ( theString = GetString( (i+131) ) ) == NIL_POINTER )
  1398.             ErrorHandler(NO_STR);
  1399.         MoveHHi((Handle)theString);
  1400.         HLock((Handle)theString);    
  1401.         topNames[i+1] = theString;
  1402.         HUnlock((Handle)theString);    
  1403.     }
  1404.         
  1405.     if (gameScore >= topScores[1])
  1406.     {
  1407.         topScores[3] = topScores[2];
  1408.         SetString(topNames[3], *topNames[2]);
  1409.         topScores[2] = topScores[1];
  1410.         SetString(topNames[2], *topNames[1]);
  1411.         topScores[1] = gameScore;
  1412.         SetString(topNames[1], name);
  1413.     }
  1414.     else if (gameScore >= topScores[2])
  1415.     {
  1416.         topScores[3] = topScores[2];
  1417.         SetString(topNames[3], *topNames[2]);
  1418.         topScores[2] = gameScore;
  1419.         SetString(topNames[2], name);
  1420.     }
  1421.     else
  1422.     {
  1423.         topScores[3] = gameScore;
  1424.         SetString(topNames[3], name);
  1425.     }
  1426.     for ( i = 0; i<=2; ++i)
  1427.     {
  1428.         if ( ( theString = GetString( i + HIGH_NAMES_STRING ) ) == NIL_POINTER )
  1429.             ErrorHandler(NO_STR);
  1430.         MoveHHi((Handle)theString);
  1431.         HLock((Handle)theString);
  1432.         SetString(theString, *topNames[i+1]);
  1433.         ChangedResource((Handle)theString);
  1434.         WriteResource((Handle)theString);
  1435.         HUnlock((Handle)theString);
  1436.         
  1437.         if ( ( theString = GetString( i + HIGH_SCORE_STRING ) ) == NIL_POINTER )
  1438.             ErrorHandler(NO_STR);
  1439.         NumToString(topScores[i+1], numString);
  1440.         SetString(theString, numString);
  1441.         ChangedResource((Handle)theString);
  1442.         WriteResource((Handle)theString);
  1443.     }
  1444.     HallOfFameDialog();
  1445. }
  1446.  
  1447. /*** GetPlayerName ***/
  1448. GetPlayerName(void)
  1449. {
  1450.     StringHandle    whichString;
  1451.     Handle            itemHandle;
  1452.     int                stringNum, itemType;
  1453.     DialogPtr        theDialog;
  1454.     int                itemHit, dialogDone = FALSE;
  1455.     GrafPtr         savePort;
  1456.     Rect            itemRect;
  1457.  
  1458.     if (gameScore >= topScores[1])
  1459.         stringNum = 500;
  1460.     else if (gameScore >=topScores[2])
  1461.         stringNum = 501;
  1462.     else
  1463.         stringNum = 502;
  1464.         
  1465.     GetPort(&savePort);
  1466.  
  1467.     if ( ( whichString = GetString( stringNum ) ) == NIL_POINTER )
  1468.         ParamText( HOPELESSLY_FATAL_ERROR, NIL_STRING, NIL_STRING, NIL_STRING);
  1469.  
  1470.     MoveHHi((Handle)whichString);
  1471.     HLock( (Handle)whichString);
  1472.     ParamText( *whichString, NIL_STRING, NIL_STRING, NIL_STRING);
  1473.     HUnlock( (Handle)whichString);
  1474.  
  1475.     if (( theDialog = GetNewDialog( PLAYER_NAME_DIALOG, NIL_POINTER, M_T_F)) 
  1476.         == NIL_POINTER)
  1477.     ErrorHandler( NO_WIND);
  1478.  
  1479.     SelIText(theDialog, PLAYER_NAME_ITEXT, 0, 255);
  1480.     dialogDone = FALSE;
  1481.     CenterWindow( theDialog);
  1482.     ShowWindow( theDialog);
  1483.     
  1484.     SetCursor(&arrow);
  1485.     
  1486.     DoTheSound( TARZAN_SOUND, TRUE );
  1487.     
  1488.     while (dialogDone == FALSE)
  1489.     {
  1490.         ModalDialog( NIL_POINTER, &itemHit);
  1491.         switch( itemHit)
  1492.         {
  1493.             case OK_BUTTON:
  1494.                 dialogDone = TRUE;
  1495.                 break;
  1496.         }
  1497.     }
  1498.     
  1499.     GetDItem( theDialog, PLAYER_NAME_ITEXT, &itemType, &itemHandle, &itemRect);
  1500.     MoveHHi((Handle)itemHandle);
  1501.     HLock(itemHandle);
  1502.     GetIText(itemHandle, &name);
  1503.     HUnlock(itemHandle);
  1504.     
  1505.     DisposDialog(theDialog);
  1506.     SetPort(savePort);
  1507. }
  1508.  
  1509. /**** AnimalPointValuesDialog ****/
  1510. AnimalPointValuesDialog(void)
  1511. {    
  1512.     DialogPtr    theDialog;
  1513.     int            itemHit, dialogDone = FALSE;
  1514.     GrafPtr savePort;
  1515.  
  1516.     GetPort(&savePort);
  1517.     
  1518.     if (( theDialog = GetNewDialog( ANIMAL_POINT_VALUES_DIALOG, NIL_POINTER, M_T_F)) 
  1519.         == NIL_POINTER)
  1520.     ErrorHandler( NO_WIND);
  1521.  
  1522.     dialogDone = FALSE;
  1523.     CenterWindow( theDialog);
  1524.     ShowWindow( theDialog);
  1525.     while (dialogDone == FALSE)
  1526.     {
  1527.         ModalDialog( NIL_POINTER, &itemHit);
  1528.         switch( itemHit)
  1529.         {
  1530.             case    RHINO:
  1531.             case    ELEPHANT:
  1532.             case    ZEBRA:
  1533.             case    GORILLA:
  1534.             case    ANTELOPE:
  1535.             case    GIRAFFE:
  1536.             case    LION:
  1537.             case    CHEETAH:
  1538.             case     WARTHOG:    
  1539.                 DoTheSound( BASE_RES_ID + itemHit, TRUE );
  1540.                 break;
  1541.             case OK_APV_DBOX:
  1542.                 dialogDone = TRUE;
  1543.                 break;
  1544.         }
  1545.     }
  1546.     DisposDialog(theDialog);
  1547.     SetPort(savePort);
  1548. }
  1549.  
  1550. /**** AboutDialog ****/
  1551. AboutDialog(void)
  1552. {    
  1553.     DialogPtr    theDialog;
  1554.     int            itemHit, dialogDone = FALSE, itemType;
  1555.     GrafPtr savePort;
  1556.     OSErr    err;
  1557.     Handle    theSnd, theIcon, itemHandle;
  1558.     Rect    itemRect;
  1559.     
  1560.     #define ICON_ITEM    5
  1561.  
  1562.     GetPort(&savePort);
  1563.     
  1564.     if (( theDialog = GetNewDialog( ABOUT_DIALOG, NIL_POINTER, M_T_F)) 
  1565.         == NIL_POINTER)
  1566.     ErrorHandler( NO_WIND);
  1567.  
  1568.     dialogDone = FALSE;
  1569.     CenterWindow( theDialog);
  1570.     ShowWindow( theDialog);
  1571.     
  1572.     GetDItem(theDialog, ICON_ITEM, &itemType, &itemHandle, &itemRect);
  1573.     theIcon = GetIcon(MY_HEAD);
  1574.     PlotIcon (&itemRect, theIcon);
  1575.     
  1576.     SetPort(theDialog);
  1577.     while (dialogDone == FALSE)
  1578.     {
  1579.         ModalDialog( NIL_POINTER, &itemHit);
  1580.         switch( itemHit)
  1581.         {
  1582.             case OK_BUTTON:
  1583.                 dialogDone = TRUE;
  1584.                 break;
  1585.             case SHOW_INTRO_SCREEN:
  1586.                 IntroDialog();
  1587.                 break;
  1588.             case HELP_BUTTON:
  1589.                 break;
  1590.             case HEAD_ICON:
  1591.                 theIcon = GetIcon(OUCH_HEAD);
  1592.                 PlotIcon(&itemRect, theIcon);
  1593.                 if (( theSnd = GetResource('snd ', OUCH_SOUND) ) 
  1594.                             == NIL_POINTER)
  1595.                     ErrorHandler( CANT_LOAD_SND);
  1596.                 SndPlay(NIL_POINTER, theSnd, FALSE);
  1597.                 theIcon = GetIcon(MY_HEAD);
  1598.                 PlotIcon(&itemRect, theIcon);
  1599.                 break;
  1600.         }
  1601.     }
  1602.     DisposDialog(theDialog);
  1603.     SetPort(savePort);
  1604. }
  1605.  
  1606. /**** HallOfFameDialog ****/
  1607. HallOfFameDialog(void)
  1608. {    
  1609.     DialogPtr    theDialog;
  1610.     int            itemHit, dialogDone = FALSE, i, itemType;
  1611.     Rect    itemRect;
  1612.     Handle    itemHandle;
  1613.     StringHandle    theString;
  1614.     GrafPtr savePort;
  1615.  
  1616.     GetPort(&savePort);
  1617.     
  1618.     if (( theDialog = GetNewDialog( HALL_OF_FAME_DIALOG, NIL_POINTER, M_T_F)) 
  1619.         == NIL_POINTER)
  1620.     ErrorHandler( NO_WIND);
  1621.     
  1622.     for (i = 0; i<=5; ++i)
  1623.     {
  1624.         if ( ( theString = GetString( (i +  128) ) ) == NIL_POINTER )
  1625.             ErrorHandler(NO_STR);
  1626.         MoveHHi((Handle)theString);
  1627.         HLock((Handle)theString);    
  1628.         GetDItem( theDialog, (i+3), &itemType, &itemHandle, &itemRect);
  1629.         SetIText( itemHandle, *theString);
  1630.         HUnlock((Handle)theString);    
  1631.     }
  1632.  
  1633.     dialogDone = FALSE;
  1634.     CenterWindow( theDialog);
  1635.     ShowWindow( theDialog);
  1636.     while (dialogDone == FALSE)
  1637.     {
  1638.         ModalDialog( NIL_POINTER, &itemHit);
  1639.         switch( itemHit)
  1640.         {
  1641.             case OK_BUTTON:
  1642.                 dialogDone = TRUE;
  1643.                 break;
  1644.             case CLEAR_SCORES_BUTTON:
  1645.                 dialogDone = TRUE;
  1646.                 ClearHighScores();
  1647.                 DrawScoreBar();
  1648.                 break;
  1649.         }
  1650.     }
  1651.     DisposDialog(theDialog);
  1652.     SetPort(savePort);
  1653. }
  1654.  
  1655. /*** ClearHighScores ***/
  1656. ClearHighScores(void)
  1657. {
  1658.     int                itemType, i;
  1659.     Rect            itemRect;
  1660.     Handle            itemHandle;
  1661.     StringHandle    theString;
  1662.     
  1663.  
  1664.     for (i = 0; i<=2; ++i)
  1665.     {
  1666.         if ( ( theString = GetString( i + HIGH_SCORE_STRING ) ) == NIL_POINTER )
  1667.                 ErrorHandler(NO_STR);
  1668.         HNoPurge((Handle)theString);
  1669.         SetString( theString, "\p0"); 
  1670.         ChangedResource((Handle)theString);
  1671.         WriteResource((Handle)theString);
  1672.         HPurge((Handle)theString);
  1673.         
  1674.         if ( ( theString = GetString( i + HIGH_NAMES_STRING ) ) == NIL_POINTER )
  1675.                 ErrorHandler(NO_STR);
  1676.         HNoPurge((Handle)theString);
  1677.         SetString( theString, "\pPlayer Name"); 
  1678.         ChangedResource((Handle)theString);
  1679.         WriteResource((Handle)theString);
  1680.         HPurge((Handle)theString);
  1681.         topScores[i+1] = 0;
  1682.     }
  1683. }
  1684.  
  1685.  
  1686. /*** CheckITextValues ***/
  1687. Boolean CheckITextValues(DialogPtr    theDialog, int dLogID)
  1688. {
  1689.     int        itemType, i;
  1690.     Rect    itemRect;
  1691.     Handle    itemHandle;
  1692.  
  1693.     long    stringValue;
  1694.     Boolean    dialogDone;
  1695.     
  1696.     dialogDone = TRUE;
  1697.     for (i = MINUTES; i <= MAX_ESCAPED; ++i)
  1698.     {
  1699.         GetDItem( theDialog, i, &itemType, &itemHandle, &itemRect);
  1700.         MoveHHi((Handle)itemHandle);
  1701.         HLock(itemHandle);
  1702.         GetIText(itemHandle, &preferenceString[i]);
  1703.         HUnlock(itemHandle);
  1704.     }
  1705.     
  1706.  
  1707.     StringToNum(&preferenceString[MAX_ESCAPED],&stringValue);
  1708.  
  1709.     if (stringValue<1 || stringValue>99)
  1710.     {
  1711.         BadValue(ESCAPED_ERROR);
  1712.         SelIText(theDialog, MAX_ESCAPED, 0, 255);
  1713.         dialogDone = FALSE;
  1714.     }
  1715.     StringToNum(&preferenceString[SECONDS],&stringValue);
  1716.     if (stringValue<0 || stringValue>59)
  1717.     {
  1718.         BadValue(SECONDS_ERROR);
  1719.         SelIText(theDialog, SECONDS, 0, 255);
  1720.         dialogDone = FALSE;
  1721.     }
  1722.     StringToNum(&preferenceString[MINUTES],&stringValue);
  1723.     if (stringValue<0 || stringValue>99)
  1724.     {
  1725.         BadValue(MINUTES_ERROR);
  1726.         SelIText(theDialog, MINUTES, 0, 255);
  1727.         dialogDone = FALSE;
  1728.     }
  1729.     return (dialogDone);
  1730. }
  1731.  
  1732. /*** CheckHighScoreDisplay ***/
  1733. CheckHighScoreDisplay(void)
  1734. {
  1735.     int        i;
  1736.     long    savedValues[8], preferenceValue[8];
  1737.     Str255    savedPrefs[8];
  1738.     StringHandle    theString;
  1739.     
  1740.     showHighScores = TRUE;
  1741.     
  1742.     for (i = 0; i<=7; ++i)
  1743.     {
  1744.         if ( ( theString = GetString( i + 200 ) ) == NIL_POINTER )
  1745.             ErrorHandler(NO_STR);
  1746.         MoveHHi((Handle)theString);
  1747.         HLock((Handle)theString);    
  1748.         StringToNum(*theString , &savedValues[i]);    
  1749.         NumToString(savedValues[i], savedPrefs[i]);
  1750.         HUnlock((Handle)theString);
  1751.         StringToNum(&preferenceString[i], &preferenceValue[i]);
  1752.     }
  1753.     
  1754.     for (i=0; i<=4; ++i)
  1755.     {
  1756.         if (savedValues[i] != preferenceValue[i]) 
  1757.             showHighScores = FALSE;
  1758.     }
  1759.     
  1760. /* This bit of code checks to see which of the 3 strings, MINUTES & SECONDS, or
  1761.     MAX_ESCAPED to check to see if the preferences match the highScorePrefs.
  1762.     This is done because, i.e. so a mismatched MINS and SECS don't screw up
  1763.     the display and recording of high score if it both preferences are set to
  1764.     be an ESCAPED_GAME */
  1765.     if (showHighScores)
  1766.     {
  1767.         switch (savedValues[TIMED_OR_ESCAPED - 200])
  1768.             {
  1769.                 case TIMED_RADIO:
  1770.                     if ( savedValues[MINUTES_STRING-200] != 
  1771.                             preferenceValue[MINUTES_STRING-200])
  1772.                             showHighScores = FALSE;
  1773.                     if ( savedValues[SECONDS_STRING-200] != 
  1774.                             preferenceValue[SECONDS_STRING-200])
  1775.                             showHighScores = FALSE;
  1776.                     break;
  1777.                 case ESCAPED_RADIO:
  1778.                     if ( savedValues[MAX_ESCAPED_STRING-200] != 
  1779.                             preferenceValue[MAX_ESCAPED_STRING-200])
  1780.                             showHighScores = FALSE;
  1781.                     break;
  1782.             }    
  1783.     }
  1784.     
  1785.     if (showHighScores)
  1786.         GetHighScores();
  1787. }
  1788.  
  1789. /**** GameOptionsDialog ****/
  1790. GameOptionsDialog(int dLogID)
  1791. {
  1792.     DialogPtr    theDialog;
  1793.     int        itemType, i, itemHit, dialogDone = FALSE;
  1794.     Rect    itemRect;
  1795.     Handle    itemHandle;
  1796.     long    stringValue;            
  1797.     GrafPtr savePort;
  1798.     StringHandle    theString, secondString;
  1799.  
  1800.     GetPort(&savePort);
  1801.  
  1802.     if (( theDialog = GetNewDialog( dLogID, NIL_POINTER, M_T_F)) 
  1803.             == NIL_POINTER)
  1804.         ErrorHandler( NO_WIND);
  1805.         
  1806.     DialogInit(theDialog, dLogID);
  1807.     
  1808.     CenterWindow( theDialog);
  1809.     ShowWindow( theDialog);
  1810.     while (dialogDone == FALSE)
  1811.     {
  1812.         ModalDialog( NIL_POINTER, &itemHit);
  1813.         switch( itemHit)
  1814.         {
  1815.             case OK_BUTTON:
  1816.                 dialogDone = CheckITextValues(theDialog, dLogID);
  1817.                 if (!dialogDone)
  1818.                 {
  1819.                     break;
  1820.                 }
  1821.                 showHighScores = FALSE;
  1822.                 CheckHighScoreDisplay();
  1823.                 SetUpGame();
  1824.                 break;
  1825.                 
  1826.             case SAVE_AND_CLEAR_BUTTON:
  1827.                 dialogDone = CheckITextValues(theDialog, dLogID);
  1828.                 if (!dialogDone)
  1829.                 {
  1830.                     break;
  1831.                 }
  1832.                 else
  1833.                 {
  1834.                     UpdatePreferences(theDialog, dLogID);    
  1835.                     ClearHighScores();
  1836.                     showHighScores = TRUE;
  1837.                     SetUpGame();
  1838.                     break;
  1839.                 }
  1840.                 
  1841.             case CANCEL_BUTTON:
  1842.                 dialogDone = TRUE;
  1843.                 break;
  1844.  
  1845.             case TIMED_RADIO:
  1846.                 GetDItem( theDialog, ESCAPED_RADIO, &itemType, &itemHandle, &itemRect);
  1847.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1848.                 GetDItem( theDialog, TIMED_RADIO, &itemType, &itemHandle, &itemRect);
  1849.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1850.                 NumToString(TIMED_RADIO, preferenceString[TIMED_OR_ESCAPED-200]);
  1851.                 break;
  1852.             case ESCAPED_RADIO:
  1853.                 GetDItem( theDialog, TIMED_RADIO, &itemType, &itemHandle, &itemRect);
  1854.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1855.                 GetDItem( theDialog, ESCAPED_RADIO, &itemType, &itemHandle, &itemRect);
  1856.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1857.                 NumToString(ESCAPED_RADIO, preferenceString[TIMED_OR_ESCAPED-200]);
  1858.                 break;
  1859.                 
  1860.             case SLOW_RADIO:
  1861.                 GetDItem( theDialog, MEDIUM_RADIO, &itemType, &itemHandle, &itemRect);
  1862.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1863.                 GetDItem( theDialog, FAST_RADIO, &itemType, &itemHandle, &itemRect);
  1864.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1865.                 GetDItem( theDialog, SLOW_RADIO, &itemType, &itemHandle, &itemRect);
  1866.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1867.                 NumToString(SLOW_RADIO, preferenceString[ANIMAL_SPEED-200]);
  1868.                 break;
  1869.             case MEDIUM_RADIO:
  1870.                 GetDItem( theDialog, SLOW_RADIO, &itemType, &itemHandle, &itemRect);
  1871.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1872.                 GetDItem( theDialog, FAST_RADIO, &itemType, &itemHandle, &itemRect);
  1873.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1874.                 GetDItem( theDialog, MEDIUM_RADIO, &itemType, &itemHandle, &itemRect);
  1875.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1876.                 NumToString(MEDIUM_RADIO, preferenceString[ANIMAL_SPEED-200]);
  1877.                 break;
  1878.             case FAST_RADIO:
  1879.                 GetDItem( theDialog, MEDIUM_RADIO, &itemType, &itemHandle, &itemRect);
  1880.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1881.                 GetDItem( theDialog, SLOW_RADIO, &itemType, &itemHandle, &itemRect);
  1882.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1883.                 GetDItem( theDialog, FAST_RADIO, &itemType, &itemHandle, &itemRect);
  1884.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1885.                 NumToString(FAST_RADIO, preferenceString[ANIMAL_SPEED-200]);
  1886.                 break;
  1887.                 
  1888.             case NINE_INCH_RADIO:
  1889.                 GetDItem( theDialog, CURRENT_SCREEN_RADIO, &itemType, &itemHandle, &itemRect);
  1890.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1891.                 GetDItem( theDialog, NINE_INCH_RADIO, &itemType, &itemHandle, &itemRect);
  1892.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1893.                 NumToString(NINE_INCH_RADIO, preferenceString[WINDOW_SIZE-200]);
  1894.                 break;
  1895.             case CURRENT_SCREEN_RADIO:
  1896.                 GetDItem( theDialog, NINE_INCH_RADIO, &itemType, &itemHandle, &itemRect);
  1897.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1898.                 GetDItem( theDialog, CURRENT_SCREEN_RADIO, &itemType, &itemHandle, &itemRect);
  1899.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1900.                 NumToString(CURRENT_SCREEN_RADIO, preferenceString[WINDOW_SIZE-200]);
  1901.                 break;
  1902.                 
  1903.             case INCREASE_YES_RADIO:
  1904.                 GetDItem( theDialog, INCREASE_NO_RADIO, &itemType, &itemHandle, &itemRect);
  1905.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1906.                 GetDItem( theDialog, INCREASE_YES_RADIO, &itemType, &itemHandle, &itemRect);
  1907.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1908.                 NumToString(INCREASE_YES_RADIO, preferenceString[INCREASE_SPEED-200]);
  1909.                 break;
  1910.             case INCREASE_NO_RADIO:
  1911.                 GetDItem( theDialog, INCREASE_YES_RADIO, &itemType, &itemHandle, &itemRect);
  1912.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1913.                 GetDItem( theDialog, INCREASE_NO_RADIO, &itemType, &itemHandle, &itemRect);
  1914.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1915.                 NumToString(INCREASE_NO_RADIO, preferenceString[INCREASE_SPEED-200]);
  1916.                 break;
  1917.                         
  1918.             case IN_ANIMAL_OUTLINE_RADIO:
  1919.                 GetDItem( theDialog, IN_BOX_SURROUNDING_ANIMAL_RADIO, &itemType, &itemHandle, &itemRect);
  1920.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1921.                 GetDItem( theDialog, IN_ANIMAL_OUTLINE_RADIO, &itemType, &itemHandle, &itemRect);
  1922.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1923.                 NumToString(IN_ANIMAL_OUTLINE_RADIO, preferenceString[SCORE_WHEN_HIT-200]);
  1924.                 break;
  1925.             case IN_BOX_SURROUNDING_ANIMAL_RADIO:
  1926.                 GetDItem( theDialog, IN_ANIMAL_OUTLINE_RADIO, &itemType, &itemHandle, &itemRect);
  1927.                 SetCtlValue( (ControlHandle)itemHandle, OFF);
  1928.                 GetDItem( theDialog, IN_BOX_SURROUNDING_ANIMAL_RADIO, &itemType, &itemHandle, &itemRect);
  1929.                 SetCtlValue( (ControlHandle)itemHandle, ON);
  1930.                 NumToString(IN_BOX_SURROUNDING_ANIMAL_RADIO, preferenceString[SCORE_WHEN_HIT-200]);
  1931.                 break;
  1932.         }
  1933.     }
  1934.     
  1935.     DisposDialog(theDialog);
  1936.     SetPort(savePort);
  1937. }
  1938.  
  1939. /*** UpdatePreferences ***/
  1940. UpdatePreferences(DialogPtr theDialog, int dLogID)
  1941. {
  1942.     int        itemType, i;
  1943.     Rect    itemRect;
  1944.     Handle    itemHandle;
  1945.     StringHandle    theString;
  1946.     
  1947.     for (i = 200; i<=207; ++i)
  1948.     {
  1949.         if ( ( theString = GetString( i ) ) == NIL_POINTER )
  1950.                 ErrorHandler(NO_STR);
  1951.         HNoPurge((Handle)theString);
  1952.         SetString( theString, preferenceString[i-200]); 
  1953.         ChangedResource((Handle)theString);
  1954.         WriteResource((Handle)theString);
  1955.         HPurge((Handle)theString);
  1956.     }
  1957. }
  1958.  
  1959. /*** DialogInit ***/
  1960. DialogInit(DialogPtr theDialog, int dLogID)
  1961. {
  1962.     int        itemType, i, baseResDiff;
  1963.     Rect    itemRect;
  1964.     Handle    itemHandle;
  1965.     Str255    myString;
  1966.     long    itemNumber;
  1967.     StringHandle    theString;
  1968.  
  1969.  
  1970.     for (i = TIMED_OR_ESCAPED; i<=SCORE_WHEN_HIT; ++i)
  1971.     {
  1972.         if ( ( theString = GetString( i ) ) == NIL_POINTER )
  1973.             ErrorHandler(NO_STR);
  1974.         MoveHHi((Handle)theString);
  1975.         HLock((Handle)theString);    
  1976.         StringToNum(*theString,&itemNumber);
  1977.         GetDItem( theDialog, itemNumber, &itemType, &itemHandle, &itemRect);
  1978.         SetCtlValue( (ControlHandle)itemHandle, ON);
  1979.         NumToString(itemNumber, preferenceString[i-200]);
  1980.         HUnlock((Handle)theString);
  1981.     }
  1982.  
  1983.     for (i = MINUTES_STRING; i<=MAX_ESCAPED_STRING; ++i)
  1984.     {
  1985.         if ( ( theString = GetString( i ) ) == NIL_POINTER )
  1986.             ErrorHandler(NO_STR);
  1987.         MoveHHi((Handle)theString);
  1988.         HLock((Handle)theString);    
  1989.         GetDItem( theDialog, (i-200), &itemType, &itemHandle, &itemRect);
  1990.         SetIText( itemHandle, *theString);
  1991.         /* item number is just a place holder in the next two lines (it's significant
  1992.             as the item number in all other code) I couldn't get the string handle
  1993.             to equate to the string, so this is my work around. I make the string
  1994.             handle a number, then make the number a string.  Ugly but functional */
  1995.         StringToNum(*theString,&itemNumber);
  1996.         NumToString(itemNumber, preferenceString[i-200]);
  1997.         HUnlock((Handle)theString);
  1998.     }
  1999. }
  2000.  
  2001. /**** BadValue ****/
  2002. BadValue(int stringNum)
  2003. {
  2004.     StringHandle    errorStringH;
  2005.     
  2006.     if ( ( errorStringH = GetString( stringNum ) ) == NIL_POINTER )
  2007.         ParamText( HOPELESSLY_FATAL_ERROR, NIL_STRING, NIL_STRING, NIL_STRING);
  2008.     else
  2009.     {
  2010.         MoveHHi((Handle)errorStringH);
  2011.         HLock( (Handle)errorStringH);
  2012.         ParamText( *errorStringH, NIL_STRING, NIL_STRING, NIL_STRING);
  2013.         HUnlock( (Handle)errorStringH);
  2014.     }
  2015.     StopAlert( ERROR_EDIT_TEXT, NIL_POINTER);
  2016. }
  2017.  
  2018. /*** IntroDialog ***/
  2019. IntroDialog(void)
  2020. {
  2021.     DialogPtr    theDialog;
  2022.     Rect    dialogRect, clippingRect, dLogOffscreenRect;
  2023.     GrafPtr savePort, dLogOffscreen;
  2024.     int            itemHit, dialogDone = FALSE, i, beginTicks, currentTicks, h;
  2025.     PicHandle    introPic;
  2026.  
  2027.     GetPort(&savePort);
  2028.  
  2029.     if (( theDialog = GetNewDialog( INTRO_DIALOG, NIL_POINTER, M_T_F)) 
  2030.             == NIL_POINTER)
  2031.         ErrorHandler( NO_WIND);
  2032.  
  2033.     dialogDone = FALSE;
  2034.     CenterWindow( theDialog);
  2035.     ShowWindow( theDialog);
  2036.     
  2037.     SetPort(theDialog);
  2038.  
  2039.     dialogRect = theDialog->portRect;
  2040.  
  2041.     if (!CreateOffscreenBitMap(&dLogOffscreen, &dialogRect)) 
  2042.     {
  2043.         SysBeep(1);
  2044.         ExitToShell();
  2045.     }
  2046.     introPic = GetPicture ( 475);
  2047.     SetPort (dLogOffscreen);
  2048.     DrawPicture(introPic, &dialogRect);
  2049.   
  2050.     SetPort(theDialog);
  2051.     
  2052.     DoTheSound(INTRO_SOUND, TRUE );
  2053.     
  2054.     h = (dialogRect.bottom-dialogRect.top)/2;
  2055.     
  2056.     SetRect(&clippingRect, dialogRect.left, h,
  2057.          dialogRect.right,h);
  2058.     for (i = 1; i<= h+1; i+=4)
  2059.     {
  2060.         ClipRect(&clippingRect);
  2061.         clippingRect.top -= 4;
  2062.         clippingRect.bottom += 4;
  2063.         CopyBits(&dLogOffscreen->portBits, &(*theDialog).portBits,&dialogRect,
  2064.             &dialogRect, srcCopy,0L);            
  2065.         beginTicks = TickCount();
  2066.         do
  2067.         {
  2068.             currentTicks = TickCount();
  2069.         }
  2070.         while ((currentTicks - beginTicks) <=2);
  2071.     }
  2072.     
  2073.     while (!(Button()));
  2074.     
  2075.     DisposDialog(theDialog);
  2076.     SetPort(savePort);
  2077. }